<template>
	<div>
		<div class="action-area">
			<el-button type="warning" @click="resetCanvas">重置</el-button>
			<el-button type="primary" @click="completeWrite">完成</el-button>
		</div>
		<div class="canvas-wrapper">
			<canvas
				id="tiankongWriterCanvas"
				class="tiankong-writer-canvas"
				:height="state.canvasHeight"
				:width="state.canvasWidth"
				@touchstart="handleStart"
				@touchmove="handleMove"
				@touchend="handleEnd"
				@mousedown="handleStart"
				@mousemove="handleMove"
				@mouseup="handleEnd"
			></canvas>
		</div>
	</div>
</template>


<script setup lang="ts">
import {defineProps, reactive, toRefs, watch, ref, onMounted} from "vue";

interface Point {
	x: number;
	y: number;
}

type Stroke = Point[];
const props = defineProps({
	//子组件接收父组件传递过来的值
	writedStroks: Array // 书写的笔画数据
})

const emit = defineEmits(['saveWritedChar', 'deleteWritedChar', 'hideWriterModal'])

const { writedStroks} = toRefs(props);
type State = {
	localSourceModal: boolean,
	dpr: number, // 屏幕分辨率
	canvasCtx: CanvasRenderingContext2D | null,
	canvasHeight: number,
	canvasWidth: number,
	strokes: Stroke[], // 笔画
	points: Point[], // 每一笔的点
	isDrawing: boolean, // 是否在画
	tempStrokes: Stroke[], // 笔画
}
const state = reactive<State>({
	localSourceModal: false,
	dpr: 1, // 屏幕分辨率
	canvasCtx: null,
	canvasHeight: 375,
	canvasWidth: 375,
	strokes: [], // 笔画
	points: [], // 每一笔的点
	isDrawing: false, // 是否在画
	tempStrokes: [], // 笔画
})
const tiankongWriterCanvas = ref()

onMounted(() => {
	if (state.canvasCtx) {
		drawBackground();
		drawWordWithStrokes(writedStroks.value);
	} else {
		const canvas = document.getElementById('tiankongWriterCanvas') as HTMLCanvasElement;
		if (canvas) {
			state.canvasCtx = canvas.getContext("2d");
			drawBackground();
			drawWordWithStrokes(writedStroks.value);
		}
	}
})

const drawBackground = () => {
	if (!state.canvasCtx) {
		return;
	}

	const lineLength = 10 * state.dpr;
	const span = 1;

	state.canvasCtx.lineWidth = 1 * state.dpr;
	state.canvasCtx.strokeStyle = "#ddd";

	// 画横线
	let hxX = 0;
	let hxY = (state.canvasHeight * state.dpr) / 2;
	state.canvasCtx.beginPath();
	state.canvasCtx.moveTo(hxX, hxY);

	while (hxX < state.canvasHeight * state.dpr) {
		state.canvasCtx.moveTo(hxX, hxY);
		state.canvasCtx.lineTo(hxX + lineLength, hxY);
		hxX += (lineLength + span) * state.dpr;
	}
	state.canvasCtx.closePath();
	state.canvasCtx.stroke();

	// 竖线
	let sxX = (state.canvasHeight * state.dpr) / 2;
	let sxY = 0;
	state.canvasCtx.beginPath();
	state.canvasCtx.moveTo(sxX, sxY);
	while (sxY < state.canvasHeight * state.dpr) {
		state.canvasCtx.moveTo(sxX, sxY);
		state.canvasCtx.lineTo(sxX, sxY + lineLength);
		sxY += (lineLength + span) * state.dpr;
	}
	state.canvasCtx.closePath();
	state.canvasCtx.stroke();

	// 斜线
	let xxX = 0;
	let xxY = 0;
	state.canvasCtx.beginPath();
	state.canvasCtx.moveTo(xxX, xxY);
	while (xxX < state.canvasHeight * state.dpr && xxY < state.canvasHeight * state.dpr) {
		state.canvasCtx.moveTo(xxX, xxY);
		state.canvasCtx.lineTo(xxX + lineLength, xxY + lineLength);
		xxX += (lineLength + span) * state.dpr;
		xxY += (lineLength + span) * state.dpr;
	}
	state.canvasCtx.closePath();
	state.canvasCtx.stroke();
	xxX = state.canvasHeight * state.dpr;
	xxY = 0;
	state.canvasCtx.beginPath();
	state.canvasCtx.moveTo(xxX, xxY);
	while (xxX > 0 && xxY < state.canvasHeight * state.dpr) {
		state.canvasCtx.moveTo(xxX, xxY);
		state.canvasCtx.lineTo(xxX - lineLength, xxY + lineLength);
		xxX -= (lineLength + span) * state.dpr;
		xxY += (lineLength + span) * state.dpr;
	}
	state.canvasCtx.closePath();
	state.canvasCtx.stroke();
}

const draw = (point: { x: number; y: number }) => {
	if (!state.canvasCtx) {
		return;
	}
	state.canvasCtx.lineWidth = 10 * state.dpr;
	state.canvasCtx.strokeStyle = "#000";
	state.canvasCtx.lineCap = "round";
	state.canvasCtx.lineJoin = "round";

	state.canvasCtx.lineTo(point.x * state.dpr, point.y * state.dpr);
	state.canvasCtx.stroke();
	state.canvasCtx.moveTo(point.x * state.dpr, point.y * state.dpr);

	state.points.push(point);
}
const getPoint = (e: MouseEvent) => {
	if (e) {
		return {x: e.offsetX, y: e.offsetY};
	} else {
		return {
			x: 0,
			y: 0,
		};
	}
}

const handleStart = (e: MouseEvent) => {
	if (!state.canvasCtx) {
		return;
	}
	state.isDrawing = true;

	let {x, y} = getPoint(e);

	state.canvasCtx.beginPath();
	state.canvasCtx.moveTo(x * state.dpr, y * state.dpr);
	state.points.push({x, y});
}

const handleMove = (e: MouseEvent) => {
	if (!state.isDrawing) {
		return;
	}
	if (!state.canvasCtx) {
		return;
	}
	draw(getPoint(e));
}

const handleEnd = (e: MouseEvent) => {
	if (!state.canvasCtx) {
		return;
	}

	state.isDrawing = false;
	state.strokes.push(state.points);
	state.points = [];
}

const resetCanvas = () => {
	if (!state.canvasCtx) {
		return;
	}

	// 刷新canvas
	state.canvasCtx.clearRect(0, 0, state.canvasHeight * state.dpr, state.canvasHeight * state.dpr);
	drawBackground();

	// 清除数据
	state.points = [];
	state.strokes = [];
}

const completeWrite = () => {
	if (!state.canvasCtx) {
		return;
	}

	if (state.strokes.length) {
		const canvasDataUrl = state.canvasCtx.canvas.toDataURL("image/png");

		emit("saveWritedChar", {
			imageUrl: canvasDataUrl,
			strokes: state.strokes,
		});
		console.log(state.strokes);
	} else {
		emit("deleteWritedChar");
	}
}

const drawWordWithStrokes = (strokes: Stroke[]) => {
	strokes.forEach((points: Point[]) => {
		if (!state.canvasCtx) {
			return;
		}

		state.canvasCtx.lineWidth = 10 * state.dpr;
		state.canvasCtx.strokeStyle = "#000";
		state.canvasCtx.lineCap = "round";
		state.canvasCtx.lineJoin = "round";

		const {x, y} = points[0];
		state.canvasCtx.beginPath();
		state.canvasCtx.moveTo(x * state.dpr, y * state.dpr);

		for (let i = 0; i < points.length; i++) {
			const point = points[i];
			state.canvasCtx.lineTo(point.x * state.dpr, point.y * state.dpr);
			state.canvasCtx.moveTo(point.x * state.dpr, point.y * state.dpr);
		}

		state.canvasCtx.closePath();
		state.canvasCtx.stroke();
	});
}

const cancel = () => {
	emit("hideWriterModal");
}
</script>

<style scoped lang="scss">
.action-area {
	width: 375px;
	margin: auto;

	display: flex;
	justify-content: space-between;
}

.canvas-wrapper {
	display: flex;
	justify-content: center;
	padding-top: 20px;

	.tiankong-writer-canvas {
		border: 1px solid red;
	}
}
</style>